﻿/* *****************************************************************************
* Creator: Rastko Šoškić - rssole@hotmail.com
* Date: 07/29/2009
* Description: Client code for ImageLoadingManager control
*
*
* ****************************************************************************** */
/// <reference name="MicrosoftAjax.js" />
/// <reference path="Resources\jquery-1.3.2-vsdoc.js" />
Type.registerNamespace("Rastko.OrderedImageLoading.Controls");

Rastko.OrderedImageLoading.Units = function()
{
    throw Error.invalidOperation("This is enumeration, it can not be instantiated.");
}

Rastko.OrderedImageLoading.Units.prototype =
{
    /// <summary>
    /// This enumeration matches System.Web.UI.WebControls.UnitType enumeration, that is,
    /// some of most common values are added here, others will be added as development advances
    /// </summary>
    Empty : 0,
    Pixel : 1,
    Point : 2,
    Percentage : 7
}

Rastko.OrderedImageLoading.Units.registerEnum("Rastko.OrderedImageLoading.Units", false);

Rastko.OrderedImageLoading.Controls.ImageLoadingManager = function()
{
    /// <summary>
    /// Client-side implementation of ImageLoadingManager control
    /// </summary>
    /// <remarks>Actually, this is more "client component" than "client control" as
    /// contains no visual elements</remarks>
    Rastko.OrderedImageLoading.Controls.ImageLoadingManager.initializeBase(this, null);

    this._imagesList = null;
    this._processedCounter = 0;
}

Rastko.OrderedImageLoading.Controls.ImageLoadingManager.prototype =
{
    initialize: function()
    {
        // Component initialization here
        var pageLoadHandler = Function.createDelegate(this, this._pageLoad);
        // As many times before, I'll repeat that this way of creating delegate
        // is necessary for proper access to "this" instance pointer within handler

        $(document).ready(pageLoadHandler);
    },

    dispose: function()
    {
        // Component disposing
    },

    get_listOfImages: function()
    {
        return this._imagesList;
    },

    set_listOfImages: function(value)
    {
        this._imagesList = value;
    },

    _pageLoad: function(e)
    {
        //Array.forEach(this._imagesList, this._initiateImageLoading, this);

        // var imageProcessing = Function.createDelegate(this, this._initiateImageLoading);

        // using setInterval "background" processing is initiated
        // this._intervalId = setInterval(imageProcessing, this.get_intervalLength());
        // There is better way to do this, without set interval...
        // ...simply, when one image is loaded, initiate next :)
        // After all, what remained is: :)
        this._initiateImageLoading();
    },

    _initiateImageLoading: function()
    {
        /// <summary>
        /// This method and loading handler below are crucial methods.
        /// This method is executed periodically (using setInterval) to check if image loading can start.
        /// </summary>

        // ---> This check has been moved to load event handler for image to automatically initiate loading of next image
        //        if (this._processedCounter < this._imagesList.length) // if not all images in list are processed
        //        {
        // this._imageLoadingInProgress = true; // set flag to true before starting loading of image
        // flag above is not necessary any more

        // id of image element to be loaded
        var imageClientId = this._imagesList[this._processedCounter].ClientID;
        // url of image which src attribute of element should be set to                
        var imageUrl = this._imagesList[this._processedCounter].ImageUrl;

        var image = $(String.format("#{0}", imageClientId)); // Retrieve particular img element
        var imageLoadHandler = Function.createDelegate(this, this._imageLoad);

        image.attr("src", imageUrl);
        image.load(imageLoadHandler); // set handler for load event of image
        // <---   }
    },

    _imageLoad: function(e)
    {
        // when image is loaded, set flag to false
        // to indicate that loading of next image can start and...
        // this._imageLoadingInProgress = false; // not necessary any more

        // Set appropriate dimensions

        var jTarget = $(e.target);
        this._setDimension(jTarget, this._imagesList[this._processedCounter].Width, "width");
        this._setDimension(jTarget, this._imagesList[this._processedCounter].Height, "height");

        // ...increase counter of "processed" images
        this._processedCounter++;

        if (this._processedCounter < this._imagesList.length) // if not all images are processed...
        {
            this._initiateImageLoading(); // ... start next :)
        }
    },

    _setDimension: function(image, dimension, dimensionName)
    {
        /// <summary>
        /// Sets width of particular image to proper value
        /// <summary>
        /// <param name="image">jQuery wrapper around image which dimension is set for</param>
        /// <param name="dimension">Width or Height object with type of unit and value</param>
        /// <param name="dimensionName">Name of dimension which should be set</param>
        /// <remarks>Width and Height objects (serialized on server into JSON) has two properties: "type" 
        /// which represents type of unit (so far, pixel, point and percentage are implemented) 
        /// and specific value</remarks>
        switch (dimension.type)
        {
            case Rastko.OrderedImageLoading.Units.Pixel:
                image.css(dimensionName, dimension.value + "px");
                break;
            case Rastko.OrderedImageLoading.Units.Point:
                image.css(dimensionName, dimension.value + "pt");
                break;
            case Rastko.OrderedImageLoading.Units.Percentage:
                image.css(dimensionName, dimension.value + "%");
                break;
            case Rastko.OrderedImageLoading.Units.Empty: // empty value...
            default: // or unknown
                break;
        }
    }
}

Rastko.OrderedImageLoading.Controls.ImageLoadingManager.registerClass(
    "Rastko.OrderedImageLoading.Controls.ImageLoadingManager", Sys.Component);